package org.grayrabbit.cloud.core.mina;

import java.net.InetSocketAddress;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.grayrabbit.cloud.core.rpc.Argument;
import org.grayrabbit.cloud.core.rpc.Result;


public class RemoteChannel implements RpcChannel {

	private String host;
	private int port;
	
	public RemoteChannel(String host,int port){
		this.host = host;
		this.port = port;
	}
	public Result invoke(Argument argument) throws RemoteInvokeException {
		IoSession session;
		NioSocketConnector connector = new NioSocketConnector();
		 connector.setConnectTimeoutMillis(30*1000l);
           connector.getFilterChain().addLast(
                   "codec",
                   new ProtocolCodecFilter(
                           new ObjectSerializationCodecFactory()));
           
       connector.getFilterChain().addLast("logger", new LoggingFilter());
       ResultHandler resultHandler = new ResultHandler(argument);
       connector.setHandler(resultHandler);
       int retry = 0;
        for (;;) {
        	retry ++;
        	try{
        	 	ConnectFuture future = connector.connect(new InetSocketAddress(host, port));
                future.awaitUninterruptibly();
                session = future.getSession();
                break;
            } catch (RuntimeIoException e) {
            	if(retry>5){
            		throw new RemoteInvokeException("超过5次连接异常",e);
            	}
//                System.err.println("Failed to connect.");
                try {
					Thread.sleep(200);
				} catch (InterruptedException e1) {
				}
            }
        }

        session.getCloseFuture().awaitUninterruptibly();
        connector.dispose();	
        //从连接中获取handler将返回结果
		return ((ResultHandler) connector.getHandler()).getResult();
	}

}